昨天我們學會了怎麼新增 Route 跟 Controller,並且知道怎麼控制要回應什麼內容給瀏覽器。
今天要使用這兩天學會的東西,我們要來看看瀏覽器到底傳了什麼給 Rails,以及 Rails 傳回什麼給瀏覽器。
我們在 app/controllers/kamigo_controller.rb
新增一個 request_headers
方法,嘗試把 request
中的 headers
傳回給瀏覽器。
class KamigoController < ApplicationController
def eat
render plain: "吃土啦"
end
def request_headers
render plain: request.headers
end
end
然後在 config/routes.rb
加入一行 get '/kamigo/request_headers', to: 'kamigo#request_headers'
。
Rails.application.routes.draw do
get '/kamigo/eat', to: 'kamigo#eat'
get '/kamigo/request_headers', to: 'kamigo#request_headers'
end
開啟網頁伺服器,並且用瀏覽器打開網頁:http://localhost:3000/kamigo/request_headers。
你會看到:
#<ActionDispatch::Http::Headers:0x0000000007ead268>
表示 request.headers
是一個 ActionDispatch::Http::Headers 物件,但是其實我們想知道的是他包含的內容是什麼,而不是他是什麼類別的物件。
所以我們需要改一下程式:
class KamigoController < ApplicationController
def eat
render plain: "吃土啦"
end
def request_headers
render plain: request.headers.to_h
end
end
加一個 to_h
,試著把物件轉成雜湊陣列看看。
{"rack.version"=>[1, 3],...
下略 180 萬字
結果是成功了,但是瀏覽器印出了 180 萬個字。
我們先試著忽略內容的部分,看一下他的關鍵字有哪些。
class KamigoController < ApplicationController
def eat
render plain: "吃土啦"
end
def request_headers
render plain: request.headers.to_h.keys
end
end
再加一個 keys
,試著把雜湊陣列轉成只包含關鍵字的陣列看看。
["rack.version", "rack.errors", "rack.multithread", "rack.multiprocess", "rack.run_once", "SCRIPT_NAME", "QUERY_STRING", "SERVER_PROTOCOL", "SERVER_SOFTWARE", "GATEWAY_INTERFACE", "REQUEST_METHOD", "REQUEST_PATH", "REQUEST_URI", "HTTP_VERSION", "HTTP_HOST", "HTTP_CONNECTION", "HTTP_CACHE_CONTROL", "HTTP_USER_AGENT", "HTTP_UPGRADE_INSECURE_REQUESTS", "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE", "HTTP_COOKIE", "HTTP_ALEXATOOLBAR_ALX_NS_PH", "HTTP_IF_NONE_MATCH", "SERVER_NAME", "SERVER_PORT", "PATH_INFO", "REMOTE_ADDR", "puma.socket", "rack.hijack?", "rack.hijack", "rack.input", "rack.url_scheme", "rack.after_reply", "puma.config", "action_dispatch.parameter_filter", "action_dispatch.redirect_filter", "action_dispatch.secret_token", "action_dispatch.secret_key_base", "action_dispatch.show_exceptions", "action_dispatch.show_detailed_exceptions", "action_dispatch.logger", "action_dispatch.backtrace_cleaner", "action_dispatch.key_generator", "action_dispatch.http_auth_salt", "action_dispatch.signed_cookie_salt", "action_dispatch.encrypted_cookie_salt", "action_dispatch.encrypted_signed_cookie_salt", "action_dispatch.cookies_serializer", "action_dispatch.cookies_digest", "action_dispatch.routes", "ROUTES_57612100_SCRIPT_NAME", "ORIGINAL_FULLPATH", "ORIGINAL_SCRIPT_NAME", "action_dispatch.request_id", "action_dispatch.remote_ip", "rack.session", "rack.session.options", "action_dispatch.request.path_parameters", "action_controller.instance", "action_dispatch.request.content_type", "action_dispatch.request.request_parameters", "rack.request.query_string", "rack.request.query_hash", "action_dispatch.request.query_parameters", "action_dispatch.request.parameters", "action_dispatch.request.formats", "rack.request.cookie_hash", "rack.request.cookie_string", "action_dispatch.cookies", "action_dispatch.request.unsigned_session_cookie"]
看起來好多了,但是這不好閱讀,我們試著讓他自己換行。
class KamigoController < ApplicationController
def eat
render plain: "吃土啦"
end
def request_headers
render plain: request.headers.to_h.keys.join("\n")
end
end
再加一個 join("\n")
,試著把陣列轉成字串,並且以 \n
作為分隔符號,\n
其實是換行的意思。
rack.version
rack.errors
rack.multithread
rack.multiprocess
rack.run_once
SCRIPT_NAME
QUERY_STRING
SERVER_PROTOCOL
SERVER_SOFTWARE
GATEWAY_INTERFACE
REQUEST_METHOD
REQUEST_PATH
REQUEST_URI
HTTP_VERSION
HTTP_HOST
HTTP_CONNECTION
HTTP_CACHE_CONTROL
HTTP_USER_AGENT
HTTP_UPGRADE_INSECURE_REQUESTS
HTTP_ACCEPT
HTTP_ACCEPT_ENCODING
HTTP_ACCEPT_LANGUAGE
HTTP_COOKIE
HTTP_ALEXATOOLBAR_ALX_NS_PH
HTTP_IF_NONE_MATCH
SERVER_NAME
SERVER_PORT
PATH_INFO
REMOTE_ADDR
puma.socket
rack.hijack?
rack.hijack
rack.input
rack.url_scheme
rack.after_reply
puma.config
action_dispatch.parameter_filter
action_dispatch.redirect_filter
action_dispatch.secret_token
action_dispatch.secret_key_base
action_dispatch.show_exceptions
action_dispatch.show_detailed_exceptions
action_dispatch.logger
action_dispatch.backtrace_cleaner
action_dispatch.key_generator
action_dispatch.http_auth_salt
action_dispatch.signed_cookie_salt
action_dispatch.encrypted_cookie_salt
action_dispatch.encrypted_signed_cookie_salt
action_dispatch.cookies_serializer
action_dispatch.cookies_digest
action_dispatch.routes
ROUTES_57612100_SCRIPT_NAME
ORIGINAL_FULLPATH
ORIGINAL_SCRIPT_NAME
action_dispatch.request_id
action_dispatch.remote_ip
rack.session
rack.session.options
action_dispatch.request.path_parameters
action_controller.instance
action_dispatch.request.content_type
action_dispatch.request.request_parameters
rack.request.query_string
rack.request.query_hash
action_dispatch.request.query_parameters
action_dispatch.request.parameters
action_dispatch.request.formats
rack.request.cookie_hash
rack.request.cookie_string
action_dispatch.cookies
action_dispatch.request.unsigned_session_cookie
我們需要過濾掉不想看的東西,但是現在還是沒有很容易閱讀,我們應該排序一下。
def request_headers
render plain: request.headers.to_h.keys.sort.join("\n")
end
再加一個 sort
,試著在轉完陣列後,先排序,再作排版文字。
GATEWAY_INTERFACE
HTTP_ACCEPT
HTTP_ACCEPT_ENCODING
HTTP_ACCEPT_LANGUAGE
HTTP_ALEXATOOLBAR_ALX_NS_PH
HTTP_CACHE_CONTROL
HTTP_CONNECTION
HTTP_COOKIE
HTTP_HOST
HTTP_IF_NONE_MATCH
HTTP_UPGRADE_INSECURE_REQUESTS
HTTP_USER_AGENT
HTTP_VERSION
ORIGINAL_FULLPATH
ORIGINAL_SCRIPT_NAME
PATH_INFO
QUERY_STRING
REMOTE_ADDR
REQUEST_METHOD
REQUEST_PATH
REQUEST_URI
ROUTES_57612100_SCRIPT_NAME
SCRIPT_NAME
SERVER_NAME
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
action_controller.instance
action_dispatch.backtrace_cleaner
action_dispatch.cookies
action_dispatch.cookies_digest
action_dispatch.cookies_serializer
action_dispatch.encrypted_cookie_salt
action_dispatch.encrypted_signed_cookie_salt
action_dispatch.http_auth_salt
action_dispatch.key_generator
action_dispatch.logger
action_dispatch.parameter_filter
action_dispatch.redirect_filter
action_dispatch.remote_ip
action_dispatch.request.content_type
action_dispatch.request.formats
action_dispatch.request.parameters
action_dispatch.request.path_parameters
action_dispatch.request.query_parameters
action_dispatch.request.request_parameters
action_dispatch.request.unsigned_session_cookie
action_dispatch.request_id
action_dispatch.routes
action_dispatch.secret_key_base
action_dispatch.secret_token
action_dispatch.show_detailed_exceptions
action_dispatch.show_exceptions
action_dispatch.signed_cookie_salt
puma.config
puma.socket
rack.after_reply
rack.errors
rack.hijack
rack.hijack?
rack.input
rack.multiprocess
rack.multithread
rack.request.cookie_hash
rack.request.cookie_string
rack.request.query_hash
rack.request.query_string
rack.run_once
rack.session
rack.session.options
rack.url_scheme
rack.version
我們需要觀察一下每一個 key 裡面包含的內容,來決定哪些是我們不要的。
def request_headers
render plain: request.headers.to_h.map{ |key, value|
key + ": " + value.class.to_s
}.sort.join("\n")
end
我們把 keys
改成了 .map{ |key, value| key + ": " + value.class.to_s}
,map 的意思是把每一筆紀錄都拿去作一個轉換,然後傳回一個陣列。
如果我們是寫成 .map{ |key, value| key }
的話,就是每一筆紀錄我們只要保留關鍵字的部分,這樣就等於 keys
,這兩段程式會有相同的結果。
但是因為我們想要看到更多的東西,所以我們再把 key
改寫成 key + ": " + value.class.to_s
,我希望在每一個 key 後面加一個冒號,然後讓 Rails 告訴我,他們是什麼類型的資料。
得到的結果是這樣:
GATEWAY_INTERFACE: String
HTTP_ACCEPT: String
HTTP_ACCEPT_ENCODING: String
HTTP_ACCEPT_LANGUAGE: String
HTTP_ALEXATOOLBAR_ALX_NS_PH: String
HTTP_CACHE_CONTROL: String
HTTP_CONNECTION: String
HTTP_COOKIE: String
HTTP_HOST: String
HTTP_UPGRADE_INSECURE_REQUESTS: String
HTTP_USER_AGENT: String
HTTP_VERSION: String
ORIGINAL_FULLPATH: String
ORIGINAL_SCRIPT_NAME: String
PATH_INFO: String
QUERY_STRING: String
REMOTE_ADDR: String
REQUEST_METHOD: String
REQUEST_PATH: String
REQUEST_URI: String
ROUTES_57612100_SCRIPT_NAME: String
SCRIPT_NAME: String
SERVER_NAME: String
SERVER_PORT: String
SERVER_PROTOCOL: String
SERVER_SOFTWARE: String
action_controller.instance: KamigoController
action_dispatch.backtrace_cleaner: Rails::BacktraceCleaner
action_dispatch.cookies: ActionDispatch::Cookies::CookieJar
action_dispatch.cookies_digest: NilClass
action_dispatch.cookies_serializer: Symbol
action_dispatch.encrypted_cookie_salt: String
action_dispatch.encrypted_signed_cookie_salt: String
action_dispatch.http_auth_salt: String
action_dispatch.key_generator: ActiveSupport::CachingKeyGenerator
action_dispatch.logger: ActiveSupport::Logger
action_dispatch.parameter_filter: Array
action_dispatch.redirect_filter: Array
action_dispatch.remote_ip: ActionDispatch::RemoteIp::GetIp
action_dispatch.request.content_type: NilClass
action_dispatch.request.formats: Array
action_dispatch.request.parameters: ActiveSupport::HashWithIndifferentAccess
action_dispatch.request.path_parameters: Hash
action_dispatch.request.query_parameters: ActiveSupport::HashWithIndifferentAccess
action_dispatch.request.request_parameters: ActiveSupport::HashWithIndifferentAccess
action_dispatch.request.unsigned_session_cookie: Hash
action_dispatch.request_id: String
action_dispatch.routes: ActionDispatch::Routing::RouteSet
action_dispatch.secret_key_base: String
action_dispatch.secret_token: NilClass
action_dispatch.show_detailed_exceptions: TrueClass
action_dispatch.show_exceptions: TrueClass
action_dispatch.signed_cookie_salt: String
puma.config: Puma::Configuration
puma.socket: TCPSocket
rack.after_reply: Array
rack.errors: IO
rack.hijack: Puma::Client
rack.hijack?: TrueClass
rack.input: Puma::NullIO
rack.multiprocess: FalseClass
rack.multithread: TrueClass
rack.request.cookie_hash: Hash
rack.request.cookie_string: String
rack.request.query_hash: Hash
rack.request.query_string: String
rack.run_once: FalseClass
rack.session.options: ActionDispatch::Request::Session::Options
rack.session: ActionDispatch::Request::Session
rack.url_scheme: String
rack.version: Array
讓我們簡化一下程式碼
def request_headers
render plain: request.headers.to_h.map{ |key, value|
"#{key}: #{value.class}"
}.sort.join("\n")
end
"#{key}: #{value.class}"
是更加簡潔的表示法,用雙引號包裝的字串可以作變數的代換,語法是 #{變數的名字}
,這種寫法的程式碼會更好閱讀。
看起來那些 key
包含 action_controller
、action_dispatch
、puma
、rack
的資料都是我們不想看到的,因為他們看起來像是 Rails 這邊才產生的資料,而不是瀏覽器傳來的資料。
我發現這些我們不想要的 key 都包含 .
,讓我們把在 key
包含 .
的資料都過濾掉。
def request_headers
render plain: request.headers.to_h.reject{ |key, value|
key.include? '.'
}.map{ |key, value|
"#{key}: #{value.class}"
}.sort.join("\n")
end
reject 可以過濾資料,滿足條件 key.include? '.'
的資料就沒有辦法進到 map。
得到的結果是這樣:
GATEWAY_INTERFACE: String
HTTP_ACCEPT: String
HTTP_ACCEPT_ENCODING: String
HTTP_ACCEPT_LANGUAGE: String
HTTP_ALEXATOOLBAR_ALX_NS_PH: String
HTTP_CACHE_CONTROL: String
HTTP_CONNECTION: String
HTTP_COOKIE: String
HTTP_HOST: String
HTTP_UPGRADE_INSECURE_REQUESTS: String
HTTP_USER_AGENT: String
HTTP_VERSION: String
ORIGINAL_FULLPATH: String
ORIGINAL_SCRIPT_NAME: String
PATH_INFO: String
QUERY_STRING: String
REMOTE_ADDR: String
REQUEST_METHOD: String
REQUEST_PATH: String
REQUEST_URI: String
ROUTES_57612100_SCRIPT_NAME: String
SCRIPT_NAME: String
SERVER_NAME: String
SERVER_PORT: String
SERVER_PROTOCOL: String
SERVER_SOFTWARE: String
現在應該可以試試看從顯示資料的類別改成顯示完整資料了。
def request_headers
render plain: request.headers.to_h.reject{ |key, value|
key.include? '.'
}.map{ |key, value|
"#{key}: #{value}"
}.sort.join("\n")
end
看起來像這樣:
GATEWAY_INTERFACE: CGI/1.2
HTTP_ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
HTTP_ACCEPT_ENCODING: gzip, deflate, br
HTTP_ACCEPT_LANGUAGE: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7,ja;q=0.6
HTTP_ALEXATOOLBAR_ALX_NS_PH: AlexaToolbar/alx-4.0
HTTP_CACHE_CONTROL: max-age=0
HTTP_CONNECTION: keep-alive
HTTP_COOKIE: _blog_session=RG5tTnJ2eUIyMkFCUFV1UHFaMDhHbXpYekJXbFhQQlBiRlk1UEhucUkvV0IwcDNtV09sNUJuVTJWOS9RU2cweTgxY0Q1TGQ5L21GRWNmS1Z6RmdEa3cxdmxFUnZPOEJObVN3ck10R3Frc2ZOWXBDT2hNY0VZUUg0RHowNlJuazFXeWJXZE5sNjlsTUFBMG12QVJNRmVnPT0tLXo3dEJjUFJtbzRjSy9HODVNcVJRRVE9PQ%3D%3D--02e477b161398d92622542cb43d8b515892b8c59; _ironman_session=SzRPTlE1VytFbFgwRUkxMHlXaDFUVlpqdzN4ekt1eVFtUFpBbmtxNUw0UFd6cytjNkI1MlBOdC9zcnBkejNUMmxLa1MzdnV6Z0dselhHOTEzSUtJTDlrU241empqS1BmanNHSTBLd1VnVzlHV2pDZis4QVVRUk5xandJaGpPNml5VHlHUTI5ZXNCa1NZdHNrNzBYT0lnPT0tLW5salNpWUNVRmlxbUI1U1ZLdXhwMGc9PQ%3D%3D--c56c1473a20c57c62c66a215e07fa14dd6f7fb94
HTTP_HOST: localhost:3000
HTTP_IF_NONE_MATCH: W/"d220fb78d8ab10894ccdd2ef500f5ac8"
HTTP_UPGRADE_INSECURE_REQUESTS: 1
HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
HTTP_VERSION: HTTP/1.1
ORIGINAL_FULLPATH: /kamigo/request_headers
ORIGINAL_SCRIPT_NAME:
PATH_INFO: /kamigo/request_headers
QUERY_STRING:
REMOTE_ADDR: 127.0.0.1
REQUEST_METHOD: GET
REQUEST_PATH: /kamigo/request_headers
REQUEST_URI: /kamigo/request_headers
ROUTES_57612100_SCRIPT_NAME:
SCRIPT_NAME:
SERVER_NAME: localhost
SERVER_PORT: 3000
SERVER_PROTOCOL: HTTP/1.1
SERVER_SOFTWARE: puma 3.11.0 Love Song
這應該就是從瀏覽器那邊傳來的全部內容了,我們可以用瀏覽器的 F12
看一下差異。
因為這樣我們無法同時看到兩邊的結果,所以需要調整一下開發人員工具的位置,把他調到右側的話會比較恰當。
先點一下這裡:
再點一下這裡:
點完之後應該會變成這樣:
仔細一看,發現這兩塊是一樣的:
再作一組 Route 和 Controller Action。
Route:
get '/kamigo/request_body', to: 'kamigo#request_body'
Action:
def request_body
render plain: request.body
end
用瀏覽器連過去看:http://localhost:3000/kamigo/request_body,發現是 #<Puma::NullIO:0x000000000673ae00>
,表示瀏覽器傳了一個空的 request body 過來,因為他是來下載網頁,不是上傳資料。如果是上傳資料的話,就會在 request body 有東西了。
再作一組 Route 和 Controller Action。
Route:
get '/kamigo/response_headers', to: 'kamigo#response_headers'
Action:
def response_headers
render plain: response.headers.to_h.map{ |key, value|
"#{key}: #{value}"
}.sort.join("\n")
end
用瀏覽器連過去看:http://localhost:3000/kamigo/response_headers。
資料少很多,這表示 Rails 回傳的東西,不是全放在 response.headers
,不過這不是很重要,知道有 response
這個東西就行了。
我們可以試著加一個 header 看看:
def response_headers
response.headers['5566'] = 'QQ'
render plain: response.headers.to_h.map{ |key, value|
"#{key}: #{value}"
}.sort.join("\n")
end
哈哈哈哈ㄚ哈
再作一組 Route 和 Controller Action。
Route:
get '/kamigo/response_body', to: 'kamigo#show_response_body'
Action:
def show_response_body
render plain: response.body
end
這裡我們不能用 response_body
,因為 response_body
已經被 Rails 用掉了,我們再用的話會出事,所以這邊稍微改一下名字。
用瀏覽器連過去看:http://localhost:3000/kamigo/response_body。
這樣會看到空的結果,因為我們傳回的內容就是 response.body
,但此時的 response.body
其實還是空值。
所以我們必須改變一下觀察的方法,其實我們可以透過小黑框來觀察 Rails 的目前狀況。
在程式碼當中加入 puts "媽我在這 \\( ̄▽ ̄)/"
意思是把 媽我在這 \\( ̄▽ ̄)/
顯示在小黑框上。
def show_response_body
puts "媽我在這 \\( ̄▽ ̄)/"
render plain: response.body
end
當有人開啟網頁 http://localhost:3000/kamigo/response_body,就會在小黑框看到這個結果:
Started GET "/kamigo/response_body" for 127.0.0.1 at 2018-01-03 03:46:48 +0800
Processing by KamigoController#show_response_body as HTML
媽我在這 \( ̄▽ ̄)/
Rendering text template
Rendered text template (0.0ms)
Completed 200 OK in 2ms (Views: 0.8ms)
所以我們利用這種方式觀察,現在把程式改成這樣:
def show_response_body
puts "===這是設定前的response.body:#{response.body}==="
render plain: "虎哇花哈哈哈"
puts "===這是設定後的response.body:#{response.body}==="
end
當有人開啟網頁 http://localhost:3000/kamigo/response_body,就會在小黑框看到這個結果:
Started GET "/kamigo/response_body" for 127.0.0.1 at 2018-01-03 03:51:40 +0800
Processing by KamigoController#show_response_body as HTML
===這是設定前的response.body:===
Rendering text template
Rendered text template (0.0ms)
===這是設定後的response.body:虎哇花哈哈哈===
Completed 200 OK in 16ms (Views: 11.5ms)
那個要抄程式碼的,都幫你整理好了。
class KamigoController < ApplicationController
def eat
render plain: "吃土啦"
end
def request_headers
render plain: request.headers.to_h.reject{ |key, value|
key.include? '.'
}.map{ |key, value|
"#{key}: #{value}"
}.sort.join("\n")
end
def response_headers
response.headers['5566'] = 'QQ'
render plain: response.headers.to_h.map{ |key, value|
"#{key}: #{value}"
}.sort.join("\n")
end
def request_body
render plain: request.body
end
def show_response_body
puts "===這是設定前的response.body:#{response.body}==="
render plain: "虎哇花哈哈哈"
puts "===這是設定後的response.body:#{response.body}==="
end
end
Rails.application.routes.draw do
get '/kamigo/eat', to: 'kamigo#eat'
get '/kamigo/request_headers', to: 'kamigo#request_headers'
get '/kamigo/request_body', to: 'kamigo#request_body'
get '/kamigo/response_headers', to: 'kamigo#response_headers'
get '/kamigo/response_body', to: 'kamigo#show_response_body'
end
http://localhost:3000/kamigo/request_headers
http://localhost:3000/kamigo/request_body
http://localhost:3000/kamigo/response_headers
http://localhost:3000/kamigo/response_body
今天就講到這裡。
嗯?今天是不是講太多了?
def response_headers
render plain: response.headers.to_h.map{ |key, value|
"#{key}: #{value}"
}.sort.join("\n")
end
這行程式我不小心把render plain: response.headers這段打成render plain: response_headers,然後當我用網址去觀看時,我的rails服務就掛掉了。按Ctrl+C也無法退出,只能關閉再一次。請問如果遇到類似的狀況有其他解法嗎?
等久一點他可能會停下來 XD
因為剛好 response_headers 是函數名稱。
舉個例:
def aaa
aaa
end
這個函數會一直不斷地呼叫自己,不會停止。跑個幾萬次之後到達一個臨界點才會停下來。你遇到的就是這個問題。
我有等他跑到終點過,但跑到終點後網頁服務器就掛掉了,只能重開cmd。測試時常常打錯指令,要一直重開服務器,所以才想說有沒有其他辦法:D
謝謝你幫我解惑
請問一下,我照著做可是卻不知道為什麼執行不出來,再麻煩協助看一下,謝謝。
https://imgur.com/CjOeS2R
https://imgur.com/Dl2AbOP
https://imgur.com/2ktqSzZ
Again (QUQ)
好吧
我發現我打錯字了 XD
XD
從 Rails 觀察 request.body那段出問題了
求解
你是不是把 alpha 打成 beta 了?
請問一下,我照著做可是卻不知道為什麼執行不出來,再麻煩協助看一下,謝謝。
https://imgur.com/CjOeS2R
https://imgur.com/Dl2AbOP
https://imgur.com/2ktqSzZ
你的輸入錯了哦,是
render plain: request.headers
不是
render plain: request_headers
你輸入 request_headers 的時候,因為你前面寫了
def request_headers
所以系統認為你在呼叫方法,然後他就一直自己叫自己,就卡死了。
想觀察request.headers 打127.0.0.1 跑出這個畫面
之前測的時候還好好的
以自行解決><